﻿using System;
using System.Collections.Generic;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;

namespace YJKInspectModel.ModelValidation.AdjoinFireZone
{
	internal class FireZoneVerWindowManage
	{
		public static bool GetDoorWinTolInfo(ref List<FindWinDoorVerInfo> lstWinDoorInfo, ViewPlan curViewPlan, UIApplication uiApp)
		{
			Document document = uiApp.ActiveUIDocument.Document;
			List<Element> doorWinOnOutwall = FireZoneVerWindowManage.GetDoorWinOnOutwall(curViewPlan, document, uiApp);
			if (doorWinOnOutwall == null || doorWinOnOutwall.Count == 0)
			{
				return false;
			}
			foreach (Element eleDoorWin in doorWinOnOutwall)
			{
				FindWinDoorVerInfo doorWinInfo = FireZoneVerWindowManage.GetDoorWinInfo(eleDoorWin, document, curViewPlan);
				if (doorWinInfo != null)
				{
					lstWinDoorInfo.Add(doorWinInfo);
				}
			}
			return true;
		}

		public static bool IsDoorWinVerAdjoin(ref CheckPairWinDoorVerInfo checkPairInfo, FindWinDoorVerInfo doorWinInfoUp, FindWinDoorVerInfo doorWinInfoDown, bool bSetSprinkler)
		{
			if (doorWinInfoUp.m_eleWinDoor.Id == doorWinInfoDown.m_eleWinDoor.Id)
			{
				return false;
			}
			double num = 0.8;
			double num2 = 1.2;
			double num3 = bSetSprinkler ? num : num2;
			XYZ xyz = null;
			XYZ xyz2 = null;
			XYZ xyz3 = null;
			XYZ xyz4 = null;
			XYZ xyz5 = null;
			XYZ xyz6 = null;
			XYZ xyz7 = null;
			XYZ xyz8 = null;
			doorWinInfoUp.GetPts(ref xyz, ref xyz2, ref xyz3, ref xyz4);
			Line line = Line.CreateBound(xyz3, xyz4);
			doorWinInfoDown.GetPts(ref xyz5, ref xyz6, ref xyz7, ref xyz8);
			Line line2 = Line.CreateBound(xyz5, xyz6);
			double val = 0.0;
			double val2 = 0.0;
			double val3 = 0.0;
			double val4 = 0.0;
			if (!FireZoneVerWindowManage.GetPtDistToLine(ref val, xyz3, line2))
			{
				return false;
			}
			if (!FireZoneVerWindowManage.GetPtDistToLine(ref val2, xyz4, line2))
			{
				return false;
			}
			if (!FireZoneVerWindowManage.GetPtDistToLine(ref val3, xyz5, line))
			{
				return false;
			}
			if (!FireZoneVerWindowManage.GetPtDistToLine(ref val4, xyz6, line))
			{
				return false;
			}
			double num4 = Math.Min(Math.Min(val, val2), Math.Min(val3, val4));
			num4 = Math.Round(num4, 2);
			if (num4 >= num3)
			{
				return false;
			}
			checkPairInfo.m_eleWinDoor1 = doorWinInfoUp.m_eleWinDoor;
			checkPairInfo.m_eleWinDoor2 = doorWinInfoDown.m_eleWinDoor;
			checkPairInfo.m_strViewPlanName1 = doorWinInfoUp.m_strViewPlanName;
			checkPairInfo.m_strViewPlanName2 = doorWinInfoDown.m_strViewPlanName;
			checkPairInfo.m_bIsFireWinDoor1 = CheckPointManage.IsFireDoorWin(checkPairInfo.m_eleWinDoor1);
			checkPairInfo.m_bIsFireWinDoor2 = CheckPointManage.IsFireDoorWin(checkPairInfo.m_eleWinDoor2);
			if (checkPairInfo.m_bIsFireWinDoor1 && checkPairInfo.m_bIsFireWinDoor2)
			{
				return false;
			}
			checkPairInfo.m_bHasSpray = bSetSprinkler;
			checkPairInfo.m_dCalDist = num4;
			checkPairInfo.m_dStandardDist = num3;
			return true;
		}

		public static bool GetPtDistToLine(ref double dDist, XYZ pt, Line line)
		{
			IntersectionResult intersectionResult = line.Project(pt);
			if (intersectionResult == null)
			{
				return false;
			}
			XYZ xyzpoint = intersectionResult.XYZPoint;
			dDist = xyzpoint.DistanceTo(pt);
			dDist = AssistFunc.feetToMM(dDist) / 1000.0;
			return true;
		}

		public static List<Element> GetDoorWinOnCurViewPlan(ViewPlan curViewPlan, Autodesk.Revit.DB.Document doc)
		{
			List<Element> doorWindowsOnViewPlan = FireZoneVerWindowManage.GetDoorWindowsOnViewPlan(doc, curViewPlan, BuiltInCategory.OST_Doors);
			List<Element> doorWindowsOnViewPlan2 = FireZoneVerWindowManage.GetDoorWindowsOnViewPlan(doc, curViewPlan, BuiltInCategory.OST_Windows);
			List<Element> list = new List<Element>();
			if (doorWindowsOnViewPlan != null && doorWindowsOnViewPlan.Count > 0)
			{
				list.AddRange(doorWindowsOnViewPlan);
			}
			if (doorWindowsOnViewPlan2 != null && doorWindowsOnViewPlan2.Count > 0)
			{
				list.AddRange(doorWindowsOnViewPlan2);
			}
			foreach (LinkedDocument linkedDocument in doc.GetLinkedDocuments())
			{
				Document document = linkedDocument.Document;
				ViewPlan viewPlanFromName = FindCrossPointsHorFireZone.GetViewPlanFromName(curViewPlan.Name, document);
				if (viewPlanFromName != null)
				{
					List<Element> doorWinOnCurViewPlan = FireZoneVerWindowManage.GetDoorWinOnCurViewPlan(viewPlanFromName, document);
					if (doorWinOnCurViewPlan != null && doorWinOnCurViewPlan.Count != 0)
					{
						list.AddRange(doorWinOnCurViewPlan);
					}
				}
			}
			return list;
		}

		public static List<Wall> GetOnFireAreaSideOutwall(ViewPlan curViewPlan, Autodesk.Revit.DB.Document doc, UIApplication uiApp)
		{
			List<Wall> outWallsCurViewPlan = FindCrossPointsHorFireZone.GetOutWallsCurViewPlan(curViewPlan, doc, uiApp);
			if (outWallsCurViewPlan.Count == 0)
			{
				return null;
			}
			List<Area> fireAreasCurViewPlan = FindCrossPointsHorFireZone.GetFireAreasCurViewPlan(curViewPlan, doc);
			if (fireAreasCurViewPlan.Count == 0)
			{
				return null;
			}
			List<Curve> list = new List<Curve>();
			foreach (Area curArea in fireAreasCurViewPlan)
			{
				List<Curve> areaBounardyCurves = FindCrossPointsHorFireZone.GetAreaBounardyCurves(curArea);
				if (FindCrossPointsHorFireZone.GetWallCurvesFromAreaBounardy(areaBounardyCurves, outWallsCurViewPlan).Count > 0)
				{
					list.AddRange(areaBounardyCurves);
				}
			}
			List<Wall> list2 = new List<Wall>();
			foreach (Wall wall in outWallsCurViewPlan)
			{
				if (FireZoneVerWindowManage.IsWallOnCurves(wall, list, uiApp))
				{
					list2.Add(wall);
				}
			}
			return list2;
		}

		public static bool IsWallOnCurves(Wall curWall, List<Curve> lstCurves, UIApplication uiApp)
		{
			Curve curve = (curWall.Location as LocationCurve).Curve;
			if (curve == null)
			{
				return false;
			}
			Curve curve2 = FireZoneVerWindowManage.CreateOffsetCurve(curve, curWall.Width / 2.0);
			if (curve2 == null)
			{
				return false;
			}
			Curve curve3 = FireZoneVerWindowManage.CreateOffsetCurve(curve, -curWall.Width / 2.0);
			if (curve3 == null)
			{
				return false;
			}
			foreach (Curve curve4 in new List<Curve>
			{
				curve,
				curve2,
				curve3
			})
			{
				foreach (Curve curve5 in lstCurves)
				{
					if (FireZoneVerWindowManage.IsTwoCurvesPartOverlap(curve4, curve5, uiApp))
					{
						return true;
					}
				}
			}
			return false;
		}

		public static bool IsTwoCurvesPartOverlap(Curve curve1, Curve curve2, UIApplication uiApp)
		{
			return CurveAssistFunc.GetOverlapType(uiApp, curve1, curve2) == OverlapType.eNotOverlap;
		}

		public static Curve CreateOffsetCurve(Curve curveIn, double dOffset)
		{
			XYZ hyendPoint = curveIn.GetEndPoint(0);
			XYZ hyendPoint2 = curveIn.GetEndPoint(1);
			Line line = curveIn as Line;
			if (line != null)
			{
				XYZ xyz = line.Direction.CrossProduct(XYZ.BasisZ);
				return YJKLineEx.YJKGetBound(hyendPoint + xyz, hyendPoint2 + xyz);
			}
			Arc arc = curveIn as Arc;
			if (arc == null)
			{
				return null;
			}
			XYZ curveMidPoint = FireZoneVerWindowManage.GetCurveMidPoint(arc);
			XYZ center = arc.Center;
			double num = arc.Radius + dOffset;
			XYZ xyz2 = (hyendPoint - center).Normalize() * num;
			XYZ xyz3 = (hyendPoint2 - center).Normalize() * num;
			XYZ xyz4 = (curveMidPoint - center).Normalize() * num;
			return Arc.Create(hyendPoint + xyz2, hyendPoint2 + xyz3, curveMidPoint + xyz4);
		}

		public static XYZ GetCurveMidPoint(Curve curveIn)
		{
			return curveIn.Evaluate(0.5, true);
		}

		public static bool IsPointOnCurve(XYZ pt, Curve curve)
		{
			XYZ hyendPoint = curve.GetEndPoint(0);
			pt = new XYZ(pt.X, pt.Y, hyendPoint.Z);
			return curve.Project(pt).XYZPoint.DistanceTo(pt) < FindCrossPointsHorFireZone.precision;
		}

		public static bool IsPointOnCurves(XYZ pt, List<Curve> lstCurves)
		{
			foreach (Curve curve in lstCurves)
			{
				if (FireZoneVerWindowManage.IsPointOnCurve(pt, curve))
				{
					return true;
				}
			}
			return false;
		}

		public static List<Element> GetDoorWinOnOutwall(ViewPlan curViewPlan, Autodesk.Revit.DB.Document doc, UIApplication uiApp)
		{
			List<Element> list = new List<Element>();
			List<Element> doorWinOnCurViewPlan = FireZoneVerWindowManage.GetDoorWinOnCurViewPlan(curViewPlan, doc);
			List<Wall> onFireAreaSideOutwall = FireZoneVerWindowManage.GetOnFireAreaSideOutwall(curViewPlan, doc, uiApp);
			if (onFireAreaSideOutwall == null || onFireAreaSideOutwall.Count == 0)
			{
				return list;
			}
			foreach (Element element in doorWinOnCurViewPlan)
			{
				if (FireZoneVerWindowManage.IsDoorWinOnWall(element, onFireAreaSideOutwall))
				{
					list.Add(element);
				}
			}
			return list;
		}

		public static FindWinDoorVerInfo GetDoorWinInfo(Element eleDoorWin, Autodesk.Revit.DB.Document doc, ViewPlan curViewPlan)
		{
			FamilyInstance familyInstance = eleDoorWin as FamilyInstance;
			ElementId elementId = eleDoorWin.get_Parameter(BuiltInParameter.FAMILY_LEVEL_PARAM).AsElementId();
			double elevation = (doc.GetElement(elementId) as Level).Elevation;
			double num = eleDoorWin.get_Parameter(BuiltInParameter.INSTANCE_SILL_HEIGHT_PARAM).AsDouble() + elevation;
			double num2 = eleDoorWin.get_Parameter(BuiltInParameter.INSTANCE_HEAD_HEIGHT_PARAM).AsDouble() + elevation;
			num = AssistFunc.feetToMM(num);
			num2 = AssistFunc.feetToMM(num2);
			return new FindWinDoorVerInfo
			{
				m_ptCenterBottom = DoorWinAssistFunc.GetInsertPt(familyInstance),
				m_dWide = DoorWinAssistFunc.GetDoorWinWidth(familyInstance),
				m_dEleBottom = num,
				m_dEleTop = num2,
				m_eleWinDoor = familyInstance,
				m_strViewPlanName = curViewPlan.Name
			};
		}

		public static bool IsDoorWinOnWall(Element curEleDoorWin, List<Wall> lstOutWall)
		{
			FamilyInstance familyInstance = curEleDoorWin as FamilyInstance;
			if (familyInstance == null)
			{
				return false;
			}
			foreach (Wall wall in lstOutWall)
			{
				if (curEleDoorWin.Document.IsLinked == wall.Document.IsLinked && curEleDoorWin.Document.PathName == wall.Document.PathName && familyInstance.Host.Id == wall.Id)
				{
					return true;
				}
			}
			return false;
		}

		public static List<Element> GetDoorWindowsOnViewPlan(Autodesk.Revit.DB.Document doc, ViewPlan viewPlan, BuiltInCategory doorOrWindowBuiltInCategory)
		{
			IEnumerable<Element> enumerable = new FilteredElementCollector(doc, viewPlan.Id).OfClass(typeof(Wall)).ToElements();
			IList<Element> list = new FilteredElementCollector(doc).OfCategory(doorOrWindowBuiltInCategory).ToElements();
			List<Element> list2 = new List<Element>();
			foreach (Element element in enumerable)
			{
				foreach (Element element2 in list)
				{
					FamilyInstance familyInstance = element2 as FamilyInstance;
					if (familyInstance != null)
					{
						Element host = familyInstance.Host;
						if (host != null && element.Id == host.Id)
						{
							list2.Add(element2);
						}
					}
				}
			}
			return list2;
		}
	}
}
